package com.ksxy.demo.chinasvgview;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.graphics.Rect;
import android.graphics.RectF;
import android.support.annotation.Nullable;
import android.support.v4.graphics.PathParser;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.MotionEvent;
import android.view.View;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

/**
 * Author: korion
 * Date:  2018/8/6
 * Email: me@korion.cn
 */
public class MapView extends View {

    private Paint paint;
    private float scale = 1.0f;
    private List<ProviceItem> provices;
    private RectF mapRect;
    private int[] colorArray = new int[]{0xFF239BD7, 0xFF30A9E5, 0xFF80CBF1, 0xFFFFFFFF};
    private ProviceItem selectItem;
    private OnProviceClickListener proviceClickListener;

    public interface OnProviceClickListener{
        void onClick(ProviceItem provice);
    }

    public MapView(Context context) {
        this(context, null);
    }

    public MapView(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MapView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
        paint = new Paint();
        paint.setAntiAlias(true);
        paint.setTextSize(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 12, getResources().getDisplayMetrics()));
        loadThread.start();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        int width = MeasureSpec.getSize(widthMeasureSpec);
        int height = MeasureSpec.getSize(heightMeasureSpec);

        if(mapRect != null){
            scale = width/mapRect.width();
        }
        setMeasuredDimension(width, height);
    }

    private Rect textRect = new Rect();
    @Override
    protected void onDraw(Canvas canvas) {
        super.onDraw(canvas);
        if(provices == null || provices.size() == 0){
            int width = getWidth();
            int height = getHeight();
            String text = "数据加载失败";
            paint.getTextBounds(text, 0, text.length(), textRect);
            int x = (width - (textRect.right - textRect.left))/2;
            int y = (height + (textRect.bottom - textRect.top))/2;
            canvas.drawText(text, x, y, paint);
        }else {
            int num = canvas.save();
            canvas.scale(scale, scale);
            for(int i=0; i < provices.size(); i++){
                ProviceItem item = provices.get(i);
                item.drawSelf(canvas, paint, item == selectItem);
            }
            canvas.restoreToCount(num);
        }
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        float x = event.getX()/scale;
        float y = event.getY()/scale;

        switch (event.getAction()){
            case MotionEvent.ACTION_DOWN:
                selectItem = handleTouch(x, y);
                if(selectItem != null){
                    return true;
                }
                break;
            case MotionEvent.ACTION_UP:
                ProviceItem item = handleTouch(x, y);
                if(item == selectItem
                        && proviceClickListener != null){
                    proviceClickListener.onClick(selectItem);
                    return true;
                }
                break;
        }
        return super.onTouchEvent(event);
    }


    public void setOnProvcieClickListener(OnProviceClickListener listener){
        this.proviceClickListener = listener;
    }

    private ProviceItem handleTouch(float x, float y){
        if(provices == null){
            return null;
        }
        ProviceItem select = null;
        for(int i=0; i < provices.size(); i++){
            if(provices.get(i).isTouch((int)x, (int)y)){
                select = provices.get(i);
                break;
            }
        }
        return select;
    }

    @SuppressLint("RestrictedApi")
    private Thread loadThread = new Thread(){
        @Override
        public void run() {
            InputStream in = getResources().openRawResource(R.raw.china2);
            List<ProviceItem> proviceItemList = new ArrayList<>();
            DocumentBuilderFactory docBuilderFactory = DocumentBuilderFactory.newInstance();
            try {
                DocumentBuilder docBuilder = docBuilderFactory.newDocumentBuilder();
                Document doc = docBuilder.parse(in);
                Element root = doc.getDocumentElement();
                NodeList pathElements = root.getElementsByTagName("path");

                float left = -1, top = -1;
                float right = -1, bottom = -1;
                RectF tempRect = new RectF();

                for(int i=0; i < pathElements.getLength(); i++){
                    Element element = (Element) pathElements.item(i);
                    String pathData = element.getAttribute("d");
                    String title = element.getAttribute("title");
                    String id = element.getAttribute("id");

                    Path path = PathParser.createPathFromPathData(pathData);
                    ProviceItem proviceItem = new ProviceItem(path, title, id);
                    proviceItemList.add(proviceItem);

                    path.computeBounds(tempRect, true);
                    left = left == -1 ? tempRect.left : Math.min(left, tempRect.left);
                    top = top == -1 ? tempRect.top : Math.min(top, tempRect.top);
                    right = right == -1 ? tempRect.right : Math.max(right, tempRect.right);
                    bottom = bottom == -1 ? tempRect.bottom : Math.max(bottom, tempRect.bottom);
                }
                mapRect = new RectF(left, top, right, bottom);
                provices = proviceItemList;
                post(ON_LOAD_FINISH);
            } catch (ParserConfigurationException
                    | SAXException
                    | IOException e) {
                e.printStackTrace();
            }
        }
    };

    private final Runnable ON_LOAD_FINISH = new Runnable() {
        @Override
        public void run() {
            if(provices == null) return;
            for(int i=0; i < provices.size(); i++){
                int color = Color.WHITE;
                color = colorArray[i%4];
                provices.get(i).setColor(color);
            }
            postInvalidate();
        }
    };
}
